package com.bruce.starts.demo.thread.forkjoin;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Splitter;
import com.google.common.collect.Maps;
import jodd.io.FileUtil;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;
import java.util.concurrent.atomic.LongAdder;
import java.util.stream.Collector;
import java.util.stream.Collectors;

public class TextWordCount {
    public static void main(String[] args) throws IOException {
        String[] lines = FileUtil.readLines("F:\\practice\\最后一支歌.txt");
        ForkJoinPool forkJoinPool = ForkJoinPool.commonPool();
        Count count = new Count(lines,0,lines.length);
        Map<String,LongAdder> result = forkJoinPool.invoke(count);
        Map<String,Long> realResult = result.entrySet().stream().filter(entry-> StringUtils.isNotBlank(entry.getKey())).collect(Collectors.toMap(Map.Entry::getKey, v->v.getValue().longValue()));
        fileCrete();
        cn.hutool.core.io.FileUtil.writeUtf8Map(realResult,new File("F:\\practice\\result.txt"),"：",true);
    }

    private static void fileCrete() throws IOException {
        File file = new File("F:\\practice\\result.txt");
        if(!file.exists()){
            file.createNewFile();
        }else {
            FileWriter fileWriter =new FileWriter(file);
            fileWriter.write("");
            fileWriter.flush();
            fileWriter.close();
        }
    }

    static class Count extends RecursiveTask<Map<String, LongAdder>>{
        private String[] lines;
        private int start;
        private int end;

        public Count(String[] lines, int start, int end) {
            this.lines = lines;
            this.start = start;
            this.end = end;
        }

        @Override
        protected Map<String, LongAdder> compute() {
            if((end-start)==1){
                return calcLine(lines[start]);
            }
            int mid = (start+end)/2;
            Count c1 = new Count(lines,start,mid);
            c1.fork();
            Count c2 = new Count(lines,mid,end);
            return meger(c2.compute(),c1.join());
        }

        private Map<String,LongAdder> meger(Map<String,LongAdder> map1,Map<String,LongAdder> map2){
            Map<String,LongAdder> result = Maps.newHashMap();
            result.putAll(map1);
            map2.forEach((k,v)-> result.computeIfAbsent(k, t->new LongAdder()).add(v.longValue()));
            return result;
        }

        private Map<String,LongAdder> calcLine(String line){
            Map<String,LongAdder> result = Maps.newHashMap();
            //String s = ":\\\\/.&*(()/*`~?<|{:。}>-,';][=-!#$%^&*+@\\";
            line = line.replaceAll("[\\pP\\p{Punct}]", "");
            String[] list = line.split("\\s+");
            Arrays.stream(list).forEach(str-> result.computeIfAbsent(str, t->new LongAdder()).increment());
            return result;
        }
    }
}
